﻿using AutoMapper;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractMainTask;
using HamcoWcs.Contract.ContractMes;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.MainTasks;
using HamcoWcs.Entitys.MesMsgQueues;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.MainTasks;
using HamcoWcs.Models.TibcoMessage;
using HamcoWcs.Models.TibcoMessage.Items;
using HamcoWcs.Service.Common;
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Xml;

namespace HamcoWcs.Service.Mes.Parsers
{
    public class MesMsgParser_PalletRequestTransportJobRequest : MesMsgParserBase
    {
        private readonly ILocationService _locationService;
        private readonly IBaseMainTaskService _mainTaskService;
        private readonly IMesCommunicateService _mesCommunicateService;
        public MesMsgParser_PalletRequestTransportJobRequest(ILoggerService loggerService, WcsDbContext wcsDbContext, IMapper mapper, ILocationService locationService, IBaseMainTaskService mainTaskService, IMesCommunicateService mesCommunicateService)
            : base(loggerService, wcsDbContext, mapper)
        {
            _locationService = locationService;
            _mainTaskService = mainTaskService;
            _mesCommunicateService = mesCommunicateService;
        }

        public override string EventName => "PALLETREQUESTTRANSPORTJOBREQUEST";

        // todo 新增PM:设备不接收MES指令，BLOCK:设备被禁用


        public override void HandleEvent(MesMsgQueue message)
        {
            string xml = message.Content;
            string res;
            PalletRequestTransportJobMessage jobMessage;
            try
            {
                res = XmlHelper.SetJobReply(xml);
                res = XmlHelper.SetXmlNodeText(res, "REPLYSUBJECTNAME", TibcoConfiguration.BasicConfiguration.RecvSubject);
                jobMessage = XmlHelper.Deserialize<PalletRequestTransportJobMessage>(xml);
            }
            catch (Exception)
            {
                _logger.AddSystemErrorLog($"MesMsgParser->PalletRequestTransportJobRequest:解析异常\r\n{xml}");
                message.Status = (int)EnumMesMsgStatus.Error;
                return;
            }

            try
            {
                CheckMesMessage(jobMessage);
                CheckDuplicatedTask(jobMessage.Body.PalletName);
                CheckPalletExists(jobMessage);

                try
                {
                    _mainTaskService.CreateTaskByMes(xml);
                    message.Status = (int)EnumMesMsgStatus.MesWait;
                }
                catch (MESJobException ex)
                {
                    message.Status = (int)EnumMesMsgStatus.WcsExcuted;
                    res = XmlHelper.SetNGReturn(res, ex.ErrorCode.ToString(), ex.Message);
                    message.Return = res;
                    return;
                }
                catch (Exception ex)
                {
                    _logger.AddSystemErrorLog($"MesMsgParser->PalletRequestTransportJobRequest:{ex.Message}");
                    throw new MESJobException(40964, "Create job has unkonw exception");
                }

                _wcsDbContext.SaveChanges();
            }
            catch (MESJobException ex)
            {
                message.Status = (int)EnumMesMsgStatus.WcsExcuted;
                res = XmlHelper.SetNGReturn(res, ex.ErrorCode.ToString(), ex.Message);
                message.Return = res;
            }
            catch (Exception ex)
            {
                message.Status = (int)EnumMesMsgStatus.WcsExcuted;
                res = XmlHelper.SetNGReturn(res, "7", "Create job has unkonw exception");
                message.Return = res;
                AddSystemErrorLog(xml, ex);
            }

        }



        public void CheckPalletExists(PalletRequestTransportJobMessage jobMessage)
        {
            if (jobMessage.Body.SourcePositionType.Equals("shelf", StringComparison.OrdinalIgnoreCase))
            {
                string palletName = jobMessage.Body.PalletName;
                var loc = _locationService.GetPalletLocation(palletName);
                if (loc == null)
                {
                    throw new MESJobException(40962, "Pallet not found in asrs");
                }

                if (!loc.ZoneName.Equals(jobMessage.Body.SourceZoneName, StringComparison.OrdinalIgnoreCase))
                {
                    throw new MESJobException(40963, "Pallet not found in target zone");
                }

                if (loc.SrmOccupyFlag || loc.IsLock)
                {
                    throw new MESJobException(40964, "Pallet blocked");
                }

                _locationService.InventoryPallet(jobMessage.Body.SourceZoneName);
            }
        }

        /// <summary>
        /// 检查MES下任务的字段是否
        /// </summary>
        /// <param name="jobMessage"></param>
        private void CheckMesMessage(PalletRequestTransportJobMessage jobMessage)
        {
            var req = jobMessage.Body;
            if (req.DestinationZoneName == req.SourceZoneName && req.SourcePositionType == "SHELF" && req.DestinationPositionType == "SHELF")
            {
                throw new MESJobException(21, "The start zone and end zone of the creation task cannot be the same");
            }

            if (req.SourceMachineName == req.DestinationMachineName && req.SourcePositionName == req.DestinationPositionName)
            {
                throw new MESJobException(22, "Error job message content:src equals des");
            }

            //if (!(req.DestinationPositionType == "SHELF" && req.DestinationPositionType == "PORT")
            // || !(req.SourcePositionType == "SHELF" && req.SourcePositionType == "PORT"))
            //{
            //    throw new MESJobException(2, "Error job message");
            //}


            if (req.DestinationPositionType == "SHELF" && string.IsNullOrEmpty(req.DestinationZoneName))
            {
                // 储位区域不得为空
                throw new MESJobException(23, "Error job message content:zone of des shelf can not be null");
            }
        }


        /// <summary>
        /// 检查是否有重复的任务
        /// </summary>
        /// <param name="unitId"></param>
        /// <exception cref="MESJobException"></exception>
        private void CheckDuplicatedTask(string unitId)
        {
            var isExistsTask = _mainTaskService.ChcekPalletTaskExists(unitId);

            if (isExistsTask)
            {
                throw new MESJobException(40965, $"Already has the pallet task");
            }
        }




        #region [Obsolete]

        //private EnumMainTaskType GetMainTaskType(string f, string t)
        //{
        //    EnumMainTaskType taskType;
        //    if (f.Equals("shelf", StringComparison.OrdinalIgnoreCase))
        //    {
        //        if (t.Equals("shelf", StringComparison.OrdinalIgnoreCase))
        //        {
        //            taskType = EnumMainTaskType.LocMoveTask;
        //        }
        //        else
        //        {
        //            taskType = EnumMainTaskType.OutboundTask;
        //        }
        //    }
        //    else
        //    {
        //        if (t.Equals("shelf", StringComparison.OrdinalIgnoreCase))
        //        {
        //            taskType = EnumMainTaskType.InboundTask;
        //        }
        //        else
        //        {
        //            taskType = EnumMainTaskType.PortMoveTask;
        //        }
        //    }

        //    return taskType;
        //}

        //private void CreateTask(string xml)
        //{
        //    var msg = XmlHelper.Deserialize<PalletRequestTransportJobMessage>(xml);
        //    var req = msg.Body;

        //    var materialInfo = XmlHelper.GetMaterialInfo(xml);

        //    var extend = new ExtendDto()
        //    {
        //        TransActionId = msg.HEADER.TRANSACTIONID,
        //        FromAddress = new MachineAddressDto()
        //        {
        //            MachineName = msg.Body.SourceMachineName,
        //            PositionName = msg.Body.SourcePositionName,
        //            PositionType = msg.Body.SourcePositionType,
        //            ZoneName = msg.Body.SourceZoneName,
        //            TransferState = ""
        //        },
        //        ToAddress = new MachineAddressDto()
        //        {
        //            MachineName = msg.Body.DestinationMachineName,
        //            PositionName = msg.Body.DestinationPositionName,
        //            PositionType = msg.Body.DestinationPositionType,
        //            ZoneName = msg.Body.DestinationZoneName,
        //            TransferState = ""
        //        },
        //        MaterialInfo = materialInfo
        //    };

        //    var mainTaskDto = new MainTaskDto()
        //    {
        //        Sender = "MES",
        //        TaskId = req.TransportJobName,
        //        UnitId = req.PalletName,
        //        FromLoc = req.SourceMachineName,
        //        ToLoc = req.DestinationMachineName,
        //        Priority = req.Priority,
        //        MainTaskType = GetMainTaskType(req.SourcePositionType, req.DestinationPositionType),
        //        TaskStatus = EnumMainTaskStatus.NewTask,
        //        Extend = extend
        //    };

        //    var mainTask = _mapper.Map<MainTask>(mainTaskDto);
        //    _wcsDbContext.MainTasks.Add(mainTask);
        //}

        #endregion
    }


    /// <summary>
    /// MES任务相关的异常
    /// </summary>
    public class MESJobException : Exception
    {
        /// <summary>
        /// 错误代码
        /// </summary>
        public int ErrorCode { get; set; }
        public MESJobException(int errorCode, string message) : base(message)
        {
            this.ErrorCode = errorCode;
        }
    }
}
